import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName Offer03
 * @Description 剑指 Offer 03. 数组中重复的数字
 * @Author clockTown
 * @Date 2021/8/15 15:54
 * @Version 1.0
 */
class Offer03 {
}

/**
 * v0 先排序，然后依次比对
 */
class Offer03V0 {
    public int findRepeatNumber(int[] nums) {
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            if (i > 0 && nums[i] == nums[i -1]){
                return nums[i];
            }
        }
        return -1;
    }
}

/**
 * v1 hashMap
 */
class Offer03V1 {
    public int findRepeatNumber(int[] nums) {
        // 使用map记录元素出现的数量， key为元素值， value为元素出现的数量
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num ,map.getOrDefault(num, 0) + 1);
            if (map.get(num) >= 2){
                return num;
            }
        }
        return -1;
    }
}

/**
 * v2 set
 */
class Offer03V2 {
    public int findRepeatNumber(int[] nums) {
        // 使用set存储元素，添加失败时返回对应的元素
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            boolean add = set.add(num);
            if (!add){
                return num;
            }
        }
        return -1;
    }
}

/**
 * 遍历中，第一次遇到数字 xx 时，将其交换至索引 xx 处；
 * 而当第二次遇到数字 xx 时，一定有 nums[x] = xnums[x]=x ，此时即可得到一组重复数字。
 */
class Offer03V3 {
    public int findRepeatNumber(int[] nums) {
        int i = 0;
        while (i < nums.length){
            if (nums[i] == i){
                i++;
                continue;
            }

            if (nums[nums[i]] == nums[i]){
                return nums[i];
            }
            int temp = nums[nums[i]];
            nums[nums[i]] = nums[i];
            nums[i] = temp;
        }
        return -1;
    }
}